package com.koudai.finance.utils;

import com.alibaba.fastjson.JSONObject;
import com.koudai.finance.constant.SysCode;
import com.koudai.finance.constant.WebConfig;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 微信授权工具类
 * @author: ls
 * @date: 2020/7/13 10:27
 */
@Component
@Slf4j
public class WxAuthUtil {

    @Resource
    private WebConfig webConfig;

    @Resource
    private RedisUtil redisUtil;

    private static final String Token = "lianshuai123";

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * @Description: 校验微信签名
     * @author: ls
     * @Date: 2020/7/11 20:55
     */
    public boolean checkSignature(String signature, String timestamp, String nonce) throws NoSuchAlgorithmException {
        String[] strArr = new String[]{Token, timestamp, nonce};
        Arrays.sort(strArr);
        String str = strArr[0] + strArr[1] + strArr[2];
        String mySignature = getSignature(str);
        return mySignature.equals(signature);
    }

    /**
     * @Description: 获取签名
     * @author: ls
     * @Date: 2020/7/21 10:23
     */
    public String getSignature(String str) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
        messageDigest.update(str.getBytes());
        byte[] bytes = messageDigest.digest();
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (byte aByte : bytes) {
            buf.append(HEX_DIGITS[(aByte >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[aByte & 0x0f]);
        }
        return buf.toString();
    }

    /**
     * @Description: 获取全局的accessToken
     * @author: ls
     * @Date: 2020/7/13 10:33
     */
    public String getGlobalAccessToken() {
        String accessToken = redisUtil.get(SysCode.WX_AUTH_GLOBAL_ACCESS_TOKEN);
        if (StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }
        String sBuilder = "https://api.weixin.qq.com/cgi-bin/token" +
                "?grant_type=client_credential" +
                "&appid=" + webConfig.getWxAppId() +
                "&secret=" + webConfig.getWxAppSecret();
        JSONObject tokenJson = HttpClientUtils.httpGet(sBuilder, null);
        accessToken = tokenJson.getString("access_token");
        if (StringUtils.isBlank(accessToken)) {
            log.error("获取微信全局accessToken失败：{}", tokenJson);
            return "";
        }
        redisUtil.set(SysCode.WX_AUTH_GLOBAL_ACCESS_TOKEN, accessToken, 110, TimeUnit.MINUTES);
        return accessToken;
    }

    /**
     * @Description: 获取用户基本信息(UnionID机制)
     * @author: ls
     * @Date: 2020/7/13 10:33
     */
    public JSONObject getUserBaseInfo(String openId) {
        JSONObject jsonObject = new JSONObject();
        String accessToken = getGlobalAccessToken();
        String sBuilder = "https://api.weixin.qq.com/cgi-bin/user/info?" +
                "access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
        JSONObject userObj = HttpClientUtils.httpGet(sBuilder, null);
        if (userObj.getInteger("subscribe") == null) {
            log.error("获取用户基本信息(UnionID机制)失败：{}", jsonObject);
            return jsonObject;
        }
        return userObj;
    }

    /**
     * @Description: 网页授权的accessToken
     * @author: ls
     * @Date: 2020/7/13 10:33
     */
    public JSONObject getPageAccessToken(String code) {
        JSONObject jsonObject = new JSONObject();
        String sBuilder = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=" + webConfig.getWxAppId() +
                "&secret=" + webConfig.getWxAppSecret() +
                "&code=" + code +
                "&grant_type=authorization_code";
        JSONObject tokenObj = HttpClientUtils.httpGet(sBuilder, null);
        if (StringUtils.isBlank(tokenObj.getString("access_token"))) {
            log.error("获取网页授权的accessToken失败：{}", tokenObj);
            return jsonObject;
        }
        String openId = tokenObj.getString("openid");
        String refreshToken = tokenObj.getString("refresh_token");
        redisUtil.set(SysCode.WX_AUTH_PAGE_REFRESH_TOKEN + openId, refreshToken, 2, TimeUnit.DAYS);
        return tokenObj;
    }

    /**
     * @Description: 获取网页授权的用户信息
     * @author: ls
     * @Date: 2020/7/13 10:33
     */
    public JSONObject getPageUserInfo(String openId) {
        JSONObject jsonObject = new JSONObject();
        // 1、先根据refreshToken获取accessToken
        String refreshToken = redisUtil.get(SysCode.WX_AUTH_PAGE_REFRESH_TOKEN + openId);
        if (StringUtils.isBlank(refreshToken)) {
            log.error("根据refreshToken获取accessToken失败：refreshToken不存在");
            return jsonObject;
        }
        String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + webConfig.getWxAppId() + "&grant_type=refresh_token&refresh_token=" + refreshToken;
        JSONObject tokenObj = HttpClientUtils.httpGet(url, null);
        if (StringUtils.isBlank(tokenObj.getString("access_token"))) {
            log.error("根据refreshToken获取accessToken失败：{}", tokenObj);
            return jsonObject;
        }
        // 2、根据accessToken获取用户信息
        String accessToken = tokenObj.getString("access_token");
        String sBuilder = "https://api.weixin.qq.com/sns/userinfo" +
                "?access_token=" + accessToken +
                "&openid=" + openId +
                "&lang=zh_CN";
        JSONObject userObj = HttpClientUtils.httpGet(sBuilder, null);
        if (StringUtils.isBlank(userObj.getString("openid"))) {
            log.error("获取网页授权的用户信息失败：{}", userObj);
            return jsonObject;
        }
        return userObj;
    }

    /**
     * @Description: 根据openId推送消息
     * @author: ls
     * @Date: 2020/7/13 14:11
     */
    public void pushWxMsg(String openId, List<WxMpTemplateData> wxMpTemplateDataList, String templateId, String url) {
        String accessToken = getGlobalAccessToken();
        String templateMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
        // 1、发送模板消息接口
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser(openId)
                .templateId(templateId)
                .build();
        // 2、跳转的url链接
        if (StringUtils.isNotBlank(url)) {
            templateMessage.setUrl(url);
        }
        // 3、添加模板数据并发送
        templateMessage.setData(wxMpTemplateDataList);
        JSONObject jsonObject = HttpClientUtils.httpPost(templateMsgUrl, templateMessage.toJson(), null);
        if (jsonObject.getIntValue("errcode") != 0) {
            log.info("推送微信模板信息失败:{}", jsonObject);
        }
    }

    /**
     * @Description: 获取微信分享的ticket
     * @author: ls
     * @Date: 2020/7/13 14:11
     */
    public String getShareTicket() {
        String ticket = redisUtil.get(SysCode.WX_AUTH_SHARE_TICKET);
        if (StringUtils.isNotBlank(ticket)) {
            return ticket;
        }
        String accessToken = getGlobalAccessToken();
        String templateMsgUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=" + accessToken;
        JSONObject jsonObject = HttpClientUtils.httpGet(templateMsgUrl, null);
        ticket = jsonObject.getString("ticket");
        if (StringUtils.isBlank(ticket)) {
            log.error("获取ticket失败：{}", jsonObject);
            return "";
        }
        redisUtil.set(SysCode.WX_AUTH_SHARE_TICKET, ticket, 110, TimeUnit.MINUTES);
        return ticket;
    }

    /**
     * @Description: 调用客服接口发送消息
     * @Author: ls
     * @Date: 2020/12/05 13:32
     */
    public void customSend(JSONObject json) {
        String accessToken = getGlobalAccessToken();
        String sBuilder = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken;
        JSONObject jsonObject = HttpClientUtils.httpPost(sBuilder, json, null);
        if (!jsonObject.getInteger("errcode").equals(0)) {
            log.error("发送消息失败：{}", jsonObject);
        }
    }

    public InputStream getQrCode() {
        //1.获取token
        String token = getGlobalAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + token;
        //2.生成临时字符串二维码:有效期10分钟,二维码类型为字符串参数值
        String data = "{\"expire_seconds\": 100000, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"lianshuaiceshi\"}}}";
        JSONObject json = HttpClientUtils.httpPost(url, data, null);
        String ticket = json.getString("ticket");
        String imgUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + ticket;
        try {
            URL url1 = new URL(imgUrl);
            HttpURLConnection httpUrl = (HttpURLConnection) url1.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();
            return httpUrl.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

